package io.alvin.ch05;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 并行搜索
 *
 * Created by Alvin on 2017/7/13.
 */
public class ParallelSearchDemo {
    static int[] arr;
    static ExecutorService pool = Executors.newCachedThreadPool();
    static final int  Thread_Num = 2;
    static AtomicInteger result = new AtomicInteger(-1);

    /**
     * 查找方法
     * @param searchValue
     * @param beginPos
     * @param endPos
     * @return
     */
    public static int search(int searchValue, int beginPos, int endPos) {
        int i = 0;
        for (i = beginPos; i < endPos; i++) {
            // 已经找到结果
            if (result.get() >= 0) {
                return result.get();
            }
            if (arr[i] == searchValue) {
                // 如果设置失败，表示其他线程已经先找到
                if (!result.compareAndSet(-1, i)) {
                    return result.get();
                }
                return i;
            }
        }
        return -1;
    }

    /**
     * 定义查找线程
     */
    public static class SearchTask implements Callable<Integer> {
        int begin,end,searchValue;

        public SearchTask(int begin, int end, int searchValue) {
            this.begin = begin;
            this.end = end;
            this.searchValue = searchValue;
        }

        public Integer call() {
            int re = search(searchValue,begin,end);
            return re;
        }
    }

    public static int pSearch(int searchValue) throws ExecutionException, InterruptedException {
        int subArrSize = arr.length/Thread_Num + 1;
        List<Future<Integer>> re = new ArrayList<Future<Integer>>();
        for (int i = 0; i < arr.length; i += subArrSize) {
            int end = i + subArrSize;
            if (end >= arr.length) {
                end = arr.length;
            }
            re.add(pool.submit(new SearchTask(searchValue,i,end)));
        }
        for (Future<Integer> future : re) {
            if (future.get() >= 0) {
                return future.get();
            }
        }
        return -1;
    }
}
